<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Configuring locking: sizing the system</title>
    <link rel="stylesheet" href="gettingStarted.css" type="text/css" />
    <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
    <link rel="start" href="index.html" title="Berkeley DB Programmer's Reference Guide" />
    <link rel="up" href="lock.html" title="Chapter 16.  The Locking Subsystem" />
    <link rel="prev" href="lock_config.html" title="Configuring locking" />
    <link rel="next" href="lock_stdmode.html" title="Standard lock modes" />
  </head>
  <body>
    <div xmlns="" class="navheader">
      <div class="libver">
        <p>Library Version 11.2.5.3</p>
      </div>
      <table width="100%" summary="Navigation header">
        <tr>
          <th colspan="3" align="center">Configuring locking: sizing the system</th>
        </tr>
        <tr>
          <td width="20%" align="left"><a accesskey="p" href="lock_config.html">Prev</a> </td>
          <th width="60%" align="center">Chapter 16. 
		The Locking Subsystem
        </th>
          <td width="20%" align="right"> <a accesskey="n" href="lock_stdmode.html">Next</a></td>
        </tr>
      </table>
      <hr />
    </div>
    <div class="sect1" lang="en" xml:lang="en">
      <div class="titlepage">
        <div>
          <div>
            <h2 class="title" style="clear: both"><a id="lock_max"></a>Configuring locking: sizing the system</h2>
          </div>
        </div>
      </div>
      <p>
        The amount of memory available to the locking system is specified
        using the <a href="../api_reference/C/envset_memory_max.html" class="olink">DB_ENV-&gt;set_memory_max()</a> method.  Sizing of the enviroment
        using the <a href="../api_reference/C/envset_memory_max.html" class="olink">DB_ENV-&gt;set_memory_max()</a> method is discussed in 
        <a class="xref" href="env_size.html" title="Sizing a database environment">Sizing a database environment</a>.  Here we will
        discuss how to estimate the number of objects your application is
        likely to lock.  Since running out of memory for locking structures
        is a fatal error requiring reconfiguration and restarting the
        environment it is best to overestimate the numbers.
    </p>
      <p>
        When configuring a Berkeley DB Concurrent Data Store application,
        the number of lock objects needed is two per open database (one for
        the database lock, and one for the cursor lock when the
        <a href="../api_reference/C/envset_flags.html#set_flags_DB_CDB_ALLDB" class="olink">DB_CDB_ALLDB</a> option is not specified).  The number of locks
        needed is one per open database handle plus one per simultaneous
        cursor or non-cursor operation.
    </p>
      <p>
        Configuring a Berkeley DB Transactional Data Store application is
        more complicated.  The recommended algorithm for selecting the
        number of locks, lockers, and lock objects is to run the
        application under stressful conditions and then review the lock
        system's statistics to determine the number of locks,
        lockers, and lock objects that were used.  Then, double these
        values for safety.  However, in some large applications, finer
        granularity of control is necessary in order to minimize the size
        of the Lock subsystem.
    </p>
      <p>
        The number of lockers can be estimated as follows:
    </p>
      <div class="itemizedlist">
        <ul type="disc">
          <li>
            If the database environment is using transactions, the 
            number of lockers can be estimated by adding the number of
            simultaneously active non-transactional cursors and open database
            handles to the number of simultaneously active transactions and
            child transactions (where a child transaction is active until
            it commits or aborts, not until its parent commits or aborts).
       </li>
          <li>
           If the database environment is not using transactions, the
           number of lockers can be estimated by adding the number
           of simultaneously active non-transactional cursors and open
           database handles to the number of simultaneous non-cursor
           operations.
        </li>
        </ul>
      </div>
      <p>
        The number of lock objects needed for a transaction
        can be estimated as follows:
    </p>
      <div class="itemizedlist">
        <ul type="disc">
          <li>
            <p>
                For each access to a non-Queue database, one lock object is
                needed for each page that is read or updated.
            </p>
          </li>
          <li>
            <p>
                For the Queue access method  you will need one lock object per
                record that is read or updated. Deleted records skipped by a
                DB_NEXT or DB_PREV operation do not require a separate lock
                object. 
            </p>
          </li>
          <li>
            <p>
                For Btree and Recno databases additional lock objects may be
                needed for each node in the btree that has to be split due to
                an update.
            </p>
          </li>
          <li>
            <p>
                For Hash and Queue databases, every access must obtain a lock on
                the metadata page for the duration of the access.  This is not
                held to the end of the transaction.
            </p>
          </li>
          <li>
            <p>
                If the transaction performs an update that needs to allocate a page
                to the database then a lock object for the metadata page will
                be needed to the end of the transaction.
            </p>
          </li>
        </ul>
      </div>
      <p>
        Note that transactions accumulate locks over the transaction lifetime,
        and the lock objects required by a single transaction is the total lock
        objects required by all of the database operations in the transaction.
        However, a database page (or record, in the case of the Queue access
        method), that is accessed multiple times within a transaction only
        requires a single lock object for the entire transaction. So if a
        transaction in your application typically accesses 10 records, that
        transaction will require about 10 lock objects (it may be a few more if
        it splits btree nodes). If you have up to 10 concurrent threads in your
        application, then you need to configure your system to have about 100
        lock objects. It is always better to configure more than you need so
        that you don't run out of lock objects. The memory overhead of
        over-allocating lock objects is minimal as they are small structures.
    </p>
      <p>
        The number of locks required by an application cannot be easily
        estimated.  It is possible to calculate a number of locks by
        multiplying the number of lockers, times the number of
        lock objects, times two (two for the two possible lock modes for each
        object, read and write). However, this is a pessimal value, and real
        applications are unlikely to actually need that many locks.  Reviewing
        the Lock subsystem statistics is the best way to determine this value.
    </p>
      <p>
        By default a minimum number of locking objects are allocated at
        startup.  To avoid contention due to allocation the application may
        use the <a href="../api_reference/C/envset_memory_init.html" class="olink">DB_ENV-&gt;set_memory_init()</a> method to preallocate and initialize
        the following lock structures:
    </p>
      <div class="itemizedlist">
        <ul type="disc">
          <li>
            <p>
                <code class="literal">DB_MEM_LOCK</code>
            </p>
            <p>
                Specifies the number of locks that can be
                simultaneously requested in the system.
            </p>
          </li>
          <li>
            <p>
                <code class="literal">DB_MEM_LOCKER</code>
            </p>
            <p>
                Specifies the number of lockers that can
                simultaneously request locks in the system.  
            </p>
          </li>
          <li>
            <p>
                <code class="literal">DB_MEM_LOCKOBJECTS</code>
            </p>
            <p>
                Specifies the number of objects that can
                simultaneously be locked in the system.  
            </p>
          </li>
        </ul>
      </div>
      <p>
        In addition to the above structures, sizing your locking subsystem
        also requires specifying the number of lock table partitions. You
        do this using the <a href="../api_reference/C/envset_lk_partitions.html" class="olink">DB_ENV-&gt;set_lk_partitions()</a> method.  Each partition
        may be accessed independently by a thread. More partitions can lead
        to higher levels of concurrency.  The default is to set the number
        of partitions to be 10 times the number of cpus that the operating
        system reports at the time the environment is created.  Having more
        than one partition when there is only one cpu is not beneficial
        because the locking system is more efficient when there is a single
        partition.  Some operating systems (Linux, Solaris) may report
        thread contexts as cpus, and so it may be necessary to override the
        default to force a single partition on a single hyperthreaded cpu
        system.  Objects and locks are divided among the partitions so it is
        best to allocate several locks and objects per partition.  The
        system will force there to be at least one per partition.  If a
        partition runs out of locks or objects it will steal what is needed
        from the other partitions.  This operation could impact performance
        if it occurs too often.  The final values specified for the locks
        and lock objects should be more than or equal to the number of lock
        table partitions.
    </p>
    </div>
    <div class="navfooter">
      <hr />
      <table width="100%" summary="Navigation footer">
        <tr>
          <td width="40%" align="left"><a accesskey="p" href="lock_config.html">Prev</a> </td>
          <td width="20%" align="center">
            <a accesskey="u" href="lock.html">Up</a>
          </td>
          <td width="40%" align="right"> <a accesskey="n" href="lock_stdmode.html">Next</a></td>
        </tr>
        <tr>
          <td width="40%" align="left" valign="top">Configuring locking </td>
          <td width="20%" align="center">
            <a accesskey="h" href="index.html">Home</a>
          </td>
          <td width="40%" align="right" valign="top"> Standard lock modes</td>
        </tr>
      </table>
    </div>
  </body>
</html>
